package net.butfly.bus.client;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import net.butfly.bus.Request;
import net.butfly.bus.Response;
import net.butfly.bus.TX;
import net.butfly.bus.context.Constants;
import net.butfly.bus.exception.BusRuntimeException;

class ClientProxy implements InvocationHandler {
	private ClientInvoker invoker;

	public ClientProxy(ClientInvoker invoker) {
		this.invoker = invoker;
	}

	public Object invoke(Object obj, Method method, Object[] args) {
		String txCode = null, txVersion = null;
		TX tx = method.getAnnotation(TX.class);
		String configTxAnnotation = ClientConfig.getTxAnnotation();
		if (tx == null) {
			Annotation[] annotations = method.getAnnotations();
			if (annotations.length > 0) {
				for (Annotation at : annotations) {
					if (configTxAnnotation != null && at.annotationType().getName().equals(configTxAnnotation)) {// 兼容之前的ebase中的TX
						String ts = at.toString();
						ts = ts.substring(ts.indexOf("(") + 1, ts.length() - 1);
						String[] tAry = ts.split(",");
						for (String t : tAry) {
							if (t.indexOf("version=") != -1) {
								txVersion = t.substring(t.indexOf("=") + 1);
							} else if (t.indexOf("value=") != -1) {
								txCode = t.substring(t.indexOf("=") + 1);
							}
						}
						break;
					}
				}
			}
		} else {
			txCode = tx.value();
			txVersion = tx.version();
		}

		if (txCode != null) {
			Request request = new Request();
			request.setTx(txCode);
			request.setVersion(txVersion);
			request.setArgs(args != null ? args : new Object[0]);

			Response response = invoker.invoke(request);
			if (response.hasError()) {
				BusRuntimeException ee;
				String em = response.getErrorMessage();
				if (em != null) {
					if (em.indexOf(":") != -1) {
						em = em.substring(em.indexOf(":") + 1);
					}
					ee = new BusRuntimeException(response.getErrorCode(), em);
				} else {
					ee = new BusRuntimeException(response.getErrorCode());
				}
				if (response.getErrorStack() != null) {
					ee.setCause(new Throwable(response.getErrorStack()));
				}
				throw ee;
			}
			return response.getResult();
		} else {
			throw new BusRuntimeException(Constants.UserError.TX_NOT_EXIST,
					"can't find tx annotation on invoked method.");
		}
	}
}
